package com.yunhe.abnormal.listener;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yunhe.abnormal.client.AuthorityClient;
import com.yunhe.abnormal.config.PushTagConfig;
import com.yunhe.common.constant.AbnormalConsts;
import com.yunhe.common.constant.KafkaConsts;
import com.yunhe.common.constant.SystemConsts;
import com.yunhe.abnormal.domain.data.AbnormalSmsConfig;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.model.PageParam;
import com.yunhe.common.model.authority.FirmDTO;
import com.yunhe.common.model.authority.StationDTO;
import com.yunhe.common.model.authority.UserDTO;
import com.yunhe.common.model.data.AlarmEventDTO;
import com.yunhe.common.model.msg.AlarmEventMsgDTO;
import com.yunhe.abnormal.service.base.AlarmNotifyConfigService;
import com.yunhe.abnormal.service.data.AbnormalSmsConfigService;
import com.yunhe.common.util.JPushUtil;
import com.yunhe.common.util.JsonUtil;
import com.yunhe.common.util.SmsUtil;
import com.yunhe.common.util.StringUtil;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 告警推送监听
 */
@Component
public class AlarmNotifyListener {
    private static final Logger logger = LoggerFactory.getLogger(AlarmNotifyListener.class);
    private ObjectMapper mapper = JsonUtil.getObjectMapper();
    @Autowired
    private AuthorityClient authorityClient;
    @Autowired
    private AbnormalSmsConfigService abnormalSmsConfigService;
    @Autowired
    private AlarmNotifyConfigService alarmNotifyConfigService;
    @Autowired
    private PushTagConfig pushTagConfig;
    /**
     * 中文告警通知短信模板号
     */
    private static final String SMS_TEMPLATE_CODE = "SMS_205460669";

    /**
     * 告警云能APP推送监听
     * @param kafkaRecord 记录
     */
    @KafkaListener(topics = KafkaConsts.Topic.AlarmEventRefresh, groupId = KafkaConsts.Group.AlarmAppPush)
    public void alarmAppListener(ConsumerRecord<?, String> kafkaRecord) throws ObjectNotFoundException, IOException {
        try {
            String value = kafkaRecord.value();
            if (!StringUtil.isEmpty(value)) {
                AlarmEventMsgDTO msg = mapper.readValue(value, AlarmEventMsgDTO.class);
                String action = msg.getAction();
                if (SystemConsts.ACTION.ADD.equals(action)) {
                    List<AlarmEventDTO> alarmEvents = msg.getAlarmEvents();
                    for (AlarmEventDTO alarmEvent : alarmEvents) {
                        String alarmLevelName = alarmEvent.getAlarmLevelName();
                        // 云能APP推送，只推送中度和严重的告警
                        if (!AbnormalConsts.ALARM_LEVEL.Moderate.equals(alarmLevelName) && !AbnormalConsts.ALARM_LEVEL.SERIOUS.equals(alarmLevelName)) {
                            continue;
                        }
                        Long stationId = alarmEvent.getStationId();
                        StationDTO station = authorityClient.getStationById(stationId).getBody().getResults();
                        //若运营商为空，则不进行推送
                        FirmDTO operator = station.getOperator();
                        if (operator == null) {
                            continue;
                        }
                        //根据运营商ID获取已配置的提醒设置，提醒设置为空，则不进行推送
                        List<AbnormalSmsConfig> configs = (List<AbnormalSmsConfig>) abnormalSmsConfigService.search(operator.getId(), Optional.empty(), Optional.empty(), new PageParam());
                        if (configs == null || configs.isEmpty()) {
                            continue;
                        }
                        //组建要推送的消息内容
                        Map<String, String> jPushMsg = getJPushMap(alarmEvent, station);
                        //遍历提醒设置 - 进行推送
                        for (AbnormalSmsConfig config : configs) {
                            Long userId = config.getUserId();
                            String tag = pushTagConfig.getAlarm() + "_" + stationId + "_" + userId;
                            JPushUtil.jpushAll(jPushMsg, tag);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("新增告警APP推送报错，{}，{}", kafkaRecord.value(), e);
        }
    }

    /**
     * 告警短信推送监听
     * @param kafkaRecord 记录
     */
    @KafkaListener(topics = KafkaConsts.Topic.AlarmEventRefresh, groupId = KafkaConsts.Group.AlarmSmsPush)
    public void alarmSmsListener(ConsumerRecord<?, String> kafkaRecord) throws ObjectNotFoundException, IOException {
        try {
            String value = kafkaRecord.value();
            if (!StringUtil.isEmpty(value)) {
                AlarmEventMsgDTO msg = mapper.readValue(value, AlarmEventMsgDTO.class);
                String action = msg.getAction();
                if (SystemConsts.ACTION.ADD.equals(action)) {
                    List<AlarmEventDTO> alarmEvents = msg.getAlarmEvents();
                    for (AlarmEventDTO alarmEvent : alarmEvents) {
                        List<UserDTO> users = alarmNotifyConfigService.needNotifyByEvent(alarmEvent);
                        if (users != null && !users.isEmpty()) {
                            String templateParam = getSmsString(alarmEvent);
                            for (UserDTO user : users) {
                                if ("+86".equals(user.getInternationalCode())) {
                                    SmsUtil.sendSms(user.getPhone(), new HashMap<>(), SMS_TEMPLATE_CODE, templateParam);
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("新增告警短信推送报错，{}，{}", kafkaRecord.value(), e);
        }
    }

    /**
     * 告警云能APP推送监听
     * @param kafkaRecord 记录
     */
    @KafkaListener(topics = KafkaConsts.Topic.AlarmEventRefresh, groupId = KafkaConsts.Group.AlarmPowerPlusAppPush)
    public void alarmPowerPlusAppListener(ConsumerRecord<?, String> kafkaRecord) throws ObjectNotFoundException, IOException {
        try {
            String value = kafkaRecord.value();
            if (!StringUtil.isEmpty(value)) {
                AlarmEventMsgDTO msg = mapper.readValue(value, AlarmEventMsgDTO.class);
                String action = msg.getAction();
                if (SystemConsts.ACTION.ADD.equals(action)) {
                    List<AlarmEventDTO> alarmEvents = msg.getAlarmEvents();
                    for (AlarmEventDTO alarmEvent : alarmEvents) {
                        String alarmLevelName = alarmEvent.getAlarmLevelName();
                        // 云能APP推送，只推送中度和严重的告警
                        if (!AbnormalConsts.ALARM_LEVEL.Moderate.equals(alarmLevelName) && !AbnormalConsts.ALARM_LEVEL.SERIOUS.equals(alarmLevelName)) {
                            continue;
                        }
                        Long stationId = alarmEvent.getStationId();
                        StationDTO station = authorityClient.getStationById(stationId).getBody().getResults();
                        //根据电站时区判断是否为中文，中文不推送
                        String timeZone = station.getTimeZone();
                        if(timeZone == null || SystemConsts.TIME_ZONE.China.equals(timeZone)) {
                            continue;
                        }
                        //若运营商为空，则不进行推送
                        FirmDTO operator = station.getOperator();
                        if (operator == null) {
                            continue;
                        }
                        //根据电站获取电站终端用户匹配PowerPlus推送
                        FirmDTO finalUser = station.getFinalUser();
                        //组建要推送的消息内容
                        Map<String, String> jPushMsg = getJPushMap(alarmEvent, station);
                        //JPush推送PowerPlus - 推送内容目前稳定为英文，以后实现判断
                        if (finalUser != null && finalUser.getContact() != null) {
                            String powerPlusTag = finalUser.getId() + "_" + finalUser.getContact();
                            try{
                                JPushUtil.jpushAllPP(jPushMsg, powerPlusTag);
                            } catch (Exception e) {
                                logger.error(e.getMessage());
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("新增告警PowerPlus推送报错，{}，{}", kafkaRecord.value(), e);
        }
    }

    /**
     * 组建极光推送消息Map
     * @param alarmEvent 告警对象
     * @param station 电站对象
     */
    private Map<String, String> getJPushMap(AlarmEventDTO alarmEvent, StationDTO station) {
        //获取记录基础信息
        String stationTitle = alarmEvent.getStationTitle();
        String devTitle = alarmEvent.getDevTitle();
        String time = alarmEvent.getStartTime();
        String alarmMessage = alarmEvent.getAlarmTitle();
        //配置推送内容
        String content;
        String title;
        //根据电站时区判断是否为中文
        String timeZone = station.getTimeZone();
        Boolean isChinese = timeZone == null || SystemConsts.TIME_ZONE.China.equals(timeZone);
        if (isChinese) {
            content = String.format("电站：%s，设备：%s于%s发生%s告警", stationTitle, devTitle, time, alarmMessage);
            title = "告警产生";
        } else {
            content = String.format("The %s of the station %s has occurred with %s on %s", devTitle, stationTitle, alarmMessage, time);
            title = "Alarm Occurred";
        }
        Map<String, String> jpushMsg = new HashMap<>();
        jpushMsg.put("msg", content);
        jpushMsg.put("title", title);
        return jpushMsg;
    }

    /**
     * 组建短信消息字符串
     * @param alarmEvent 告警对象
     */
    private String getSmsString(AlarmEventDTO alarmEvent) {
        String stationTitle = alarmEvent.getStationTitle();
        String devTitle = alarmEvent.getDevTitle();
        String time = alarmEvent.getStartTime();
        String alarmMessage = alarmEvent.getAlarmTitle();
        //配置Sms短信推送内容 - 目前未添加英文短信模板
        String record = alarmEvent.getRecords();
        if (cn.jiguang.common.utils.StringUtils.isNotEmpty(record)) {
            alarmMessage += (", 详情：" + record);
        }
        return String.format("{\"time\":\"%s\",\"stationTitle\":\"%s\",\"devTitle\":\"%s\",\"alarm\":\"%s\"}", time, stationTitle, devTitle, alarmMessage);
    }
}
